oo::class create AppMenu {
    mixin Monitor
    variable Menu Label NotebookObj Notebook

    constructor {menubar label} {
        set Menu [menu $menubar.$label -tearoff 0]
        set Label [string totitle $label]
        $menubar add cascade -menu $Menu -label $Label -underline 0
    }

    method createMenu {} {}

    method setNotebook {nbObj} {
        set NotebookObj $nbObj
        set Notebook [set [info object namespace $NotebookObj]::Notebook]
        # ...
        my createMenu
    }

    method createItem {row} {
        foreach {type data} $row {}
        my create[string totitle $type]Item $data
    }

    method configureMenuEntry {label accelerator command underline} {
	if {$command != {}} {
	    $Menu entryconfigure $label -command [list [self object] [string trimleft $command +]]
	} else {
	    if {$accelerator != {}} {
		$Menu entryconfigure $label -command \
		    [list [self object] eventGenerator [my getEvent $accelerator]]
	    }
	}
	if {$accelerator != {}} {
	    $Menu entryconfigure $label -accelerator $accelerator
	    if {$command != {}} {
		my bindToNotebook $accelerator [my createCommand $command]
	    }
	}
	if {$underline != {}} {
	    $Menu entryconfigure $label -underline $underline
	}
    }

    method createCheckItem {data} {
	foreach {label accelerator underline command globalVar} $data {
	    set label [format %-12s $label]
	    $Menu add check -label $label -variable $globalVar
	    my configureMenuEntry $label $accelerator $command $underline
	}
    }

    method createCommandItem {data} {
        foreach {label accelerator underline command} $data {
            set label [format %-12s $label]
            $Menu add command -label $label
            my configureMenuEntry $label $accelerator $command $underline
        }
    }

    method createCommand {command} {
        if ![string first + $command] {
            return [list + [self object] [string trimleft $command +]]
        } else {
            return [list [self object] $command]
        }
    }

    method eventGenerator {accelerator} {
        set padWidget [my getCurrentPadWidget]
        focus $padWidget
        event generate $padWidget $accelerator -when tail
    }

    method getCurrentPadWidget {} {
        set containerObj [$NotebookObj getContainObj \
                              [$Notebook index current]]
        set codePad [set [info object namespace $containerObj]::CodePad]
        return [set [info object namespace $codePad]::PadWidget]
    }

    method createSeparatorItem {args} {
        $Menu add separator
    }

    method getEvent {accelerator} {
        if {[string first - $accelerator] == -1} {
            return <$accelerator>
        }
        # Composed Key
        foreach {modifier key} [split $accelerator -] {}
        switch $modifier {
            C {set modifier Control}
            A {set modifier Alt}
            S {set modifier Shift}
        }
        return <$modifier-$key>
    }

    method bindToNotebook {accelerator command} {
        bind . [my getEvent $accelerator] $command
    }

    destructor {
        destroy $Menu
    }
}